﻿namespace Unity.SerializationLogic
{
    using Mono.Cecil;
    using System;
    using System.Collections.Generic;
    using Unity.CecilTools.Extensions;

    public class UnityEngineTypePredicates
    {
        private const string AnimationCurve = "UnityEngine.AnimationCurve";
        private const string Gradient = "UnityEngine.Gradient";
        protected const string GUIStyle = "UnityEngine.GUIStyle";
        private const string MonoBehaviour = "UnityEngine.MonoBehaviour";
        protected const string RectOffset = "UnityEngine.RectOffset";
        private const string ScriptableObject = "UnityEngine.ScriptableObject";
        private const string SerializeFieldAttribute = "UnityEngine.SerializeField";
        private static readonly HashSet<string> TypesThatShouldHaveHadSerializableAttribute = new HashSet<string> { "Vector3", "Vector2", "Vector4", "Rect", "Quaternion", "Matrix4x4", "Color", "Color32", "LayerMask" };
        protected const string UnityEngineObject = "UnityEngine.Object";

        public static bool IsAnimationCurve(TypeReference type)
        {
            return type.IsAssignableTo("UnityEngine.AnimationCurve");
        }

        public static bool IsGradient(TypeReference type)
        {
            return type.IsAssignableTo("UnityEngine.Gradient");
        }

        public static bool IsGUIStyle(TypeReference type)
        {
            return type.IsAssignableTo("UnityEngine.GUIStyle");
        }

        private static bool IsMonoBehaviour(TypeDefinition typeDefinition)
        {
            return typeDefinition.IsSubclassOf("UnityEngine.MonoBehaviour");
        }

        public static bool IsMonoBehaviour(TypeReference type)
        {
            return IsMonoBehaviour(type.CheckedResolve());
        }

        public static bool IsRectOffset(TypeReference type)
        {
            return type.IsAssignableTo("UnityEngine.RectOffset");
        }

        private static bool IsScriptableObject(TypeDefinition temp)
        {
            return temp.IsSubclassOf("UnityEngine.ScriptableObject");
        }

        public static bool IsScriptableObject(TypeReference type)
        {
            return IsScriptableObject(type.CheckedResolve());
        }

        public static bool IsSerializeFieldAttribute(TypeReference attributeType)
        {
            return (attributeType.FullName == "UnityEngine.SerializeField");
        }

        public static bool IsUnityEngineObject(TypeReference type)
        {
            if (type.IsArray)
            {
                return false;
            }
            return ((type.FullName == "UnityEngine.Object") || type.CheckedResolve().IsSubclassOf("UnityEngine.Object"));
        }

        public static bool IsUnityEngineValueType(TypeReference type)
        {
            return ((type.SafeNamespace() == "UnityEngine") && TypesThatShouldHaveHadSerializableAttribute.Contains(type.Name));
        }

        public static bool ShouldHaveHadSerializableAttribute(TypeReference type)
        {
            return IsUnityEngineValueType(type);
        }
    }
}

